﻿
using System ;
using System.Drawing ;
using System.Windows.Forms ;
using System.Collections.Generic ;

using MskEdit.Msk.Model ;


namespace MskEdit.Msk.Frontend
{
    public partial class MskPagePanel : Panel
    {
        #region Private data

        Size                pageSize_ ;
        MskFieldGeometer    fieldGeometer_ ;
        bool                hasVisibleGrid_ ;
        
        static int      COLS = 80 ;
        static int      ROWS = 40 ;

        MskFieldRadioCollection mskFieldRadioCollection_ ;
        
        #endregion

        #region Private members

        private void paintGrid() {
        
            Graphics g = this.CreateGraphics() ;
            Color lineColor = Color.DarkSlateBlue ;
            Pen   linePen   = new Pen( lineColor ) ;
            Size  cellSize  = fieldGeometer_.getFieldCellSize() ;
            
            for ( int col = 0 ; col <= this.Width ; ++col ) {
                int x = cellSize.Width * col ;
                g.DrawLine( linePen, x, 0, x, this.Height ) ;
            }

            for ( int row = 0 ; row <= this.Height ; ++row ) {
                int y = cellSize.Height * row ;
                g.DrawLine( linePen, 0, y, this.Width, y ) ;
            }

            linePen.Dispose() ;
            g.Dispose() ;
        }

        #endregion

        #region Private event handlers

        private void handlePaint( object obj, PaintEventArgs args ) {
            
            if ( hasVisibleGrid_ )
                paintGrid() ;
        }


        private void handleLineSelectionChanged( MskLineKey mskLineKey ) {
        
            if ( LineSelectionChanged == null )
                return ;
                
            LineSelectionChanged.Invoke( mskLineKey ) ;
        }
        
        
        private void handleVisibleGridChange( bool showGrid ) {
            hasVisibleGrid_ = showGrid ;
            this.Invalidate() ;
        }

        #endregion
        
        #region Private foundation

        private static void initPanel( Size cellSize, MskPagePanel mskPagePanel ) {
        
            mskPagePanel.BackColor = Color.FromArgb( 119, 165, 222 ) ;
            mskPagePanel.Location = new Point( cellSize ) ;
            mskPagePanel.Size = new Size( cellSize.Width*90, cellSize.Height*32 ) ;
        }


        private static void populatePanel( MskPage mskPage, MskFieldGeometer fieldGeometer, MskPagePanel mskPagePanel ) {
        
            foreach ( string line in mskPage.Lines ) {
            
                MskLine mskLine = MskLine.TryFrom( line, null ) ;
                if ( mskLine == null )
                    continue ;
                                        
                MskFieldUserControl mskFieldUserControl = MskFieldUserControl.From( mskLine, fieldGeometer, mskPagePanel.BackColor ) ; 

                mskPagePanel.Controls.Add( mskFieldUserControl ) ;
                mskPagePanel.mskFieldRadioCollection_.Add( mskLine.LineKey, mskFieldUserControl ) ;
            }
        }


        private MskPagePanel( MskFieldGeometer fieldGeometer, bool showGrid ) {

            InitializeComponent() ;
            
            mskFieldRadioCollection_ = new MskFieldRadioCollection() ;
            mskFieldRadioCollection_.SelectionChanged += handleLineSelectionChanged ;
            
            pageSize_       = new Size( COLS, ROWS ) ;
            fieldGeometer_  = fieldGeometer ;
            hasVisibleGrid_ = showGrid ;
            
            this.Paint += handlePaint ;
        }

        #endregion

        #region Public foundation

        public static MskPagePanel From( MskPage mskPage, MskFieldGeometer fieldGeometer, bool showGrid ) {
        
            MskPagePanel mskPagePanel = new MskPagePanel( fieldGeometer, showGrid ) ;
            initPanel( fieldGeometer.getFieldCellSize(), mskPagePanel ) ;
            populatePanel( mskPage, fieldGeometer, mskPagePanel ) ;
            
            return mskPagePanel ;
        }

        #endregion

        #region Public event declarations

        public delegate void LineSelectionChangedEventHandler( MskLineKey mskLineKey ) ;
        public event LineSelectionChangedEventHandler LineSelectionChanged ;

        #endregion

        #region Public modifiers
        
        public void updateMskLine( MskLine mskLine ) {
        
            MskLineKey mskLineKey = mskLine.LineKey ;
            
            if ( ! mskFieldRadioCollection_.Dictionary.ContainsKey( mskLineKey ) )
                return ;
                
            mskFieldRadioCollection_.Dictionary[ mskLineKey ].UpdateMskLine( mskLine, fieldGeometer_ ) ;
        }
        
        public void clearMskLineSelection() {
            mskFieldRadioCollection_.clearCurrentSelection() ;
        }

        #endregion

        #region Public properties

        public bool HasVisibleGrid {
            get { return hasVisibleGrid_ ; }
            set { handleVisibleGridChange( value ) ; }
        }

        #endregion
    }
}
